<script>
import {
  Back,
  Next,
  FormatBrush,
  AdjacentItem,
  AddSubset,
  Delete,
  Picture,
  SmilingFace,
  Link,
  EditOne,
  TagOne,
  Save,
  FullScreenOne,
} from "@icon-park/vue-next";
import MindMap from "simple-mind-map";
import MindMapBarButton from "../../../components/MindMapBarButton.vue";
import { nodeIconList } from "simple-mind-map/src/svg/icons";
import { UploadFilled } from "@element-plus/icons-vue";
import { ElMessage, genFileId } from "element-plus";
import Request from "../../../utils/Request";
import store from "../../../store/index.js";

export default {
  components: {
    MindMapBarButton,
    FormatBrush,
    UploadFilled,
  },
  props: {
    id: String,
    index: Number,
  },
  data() {
    return {
      firstContent: true,
      mindMapEl: null,
      mindMap: null,
      // mindMapData: {
      //   data: {
      //     text: "根节点",
      //   },
      //   children: [],
      // },
      activeNodes: [],
      currentIconList: [],
      isStart: true,
      isEnd: true,
      iconDrawerVisible: false,
      nodeIconList,
      setLinkDialog: false,
      setLinkData: {
        url: "",
        alt: "",
      },
      formatBrushStyles: null,
      setImgDialog: false,
      setImgData: {},
      setImgMode: "url",
      setImgIsUpload: false,
    };
  },
  methods: {
    async initMindMap() {
      this.mindMap = new MindMap({
        el: document.getElementById("mindMapContainer"),
        data: null,
      });
      // 监听节点激活事件
      this.mindMap.on("node_active", (node, activeNodeList) => {
        // console.log(activeNodeList);
        // console.log(this.mindMapData);
        this.activeNodes = activeNodeList;
        if (this.activeNodes.length > 0) {
          let firstNode = this.activeNodes[0];
          this.currentIconList = firstNode.getData("icon") || [];

          // 格式刷
          if (this.formatBrushStyles != null) {
            // console.log(this.formatBrushStyles);
            this.activeNodes.forEach((n) => {
              // object formatBrushStyles 遍历
              for (let k in this.formatBrushStyles) {
                n.setStyle(k, this.formatBrushStyles[k]);
              }
              // n.effectiveStyles = this.formatBrushStyles;
            });
            this.formatBrushStyles = null;
          }
        } else {
          this.currentIconList = [];
        }
      });
      // 监听回退和前进按钮状态变化事件
      this.mindMap.on("back_forward", (index, len) => {
        this.isStart = index <= 0;
        this.isEnd = index >= len - 1;
      });
      // 监听快捷键事件
      this.mindMap.keyCommand.addShortcut("Control+s", this.saveMindMap);
      // 监听数据变化事件
      this.mindMap.on("data_change", (data) => {
        if (!store.state.planeTabIsModified[this.index]) {
          if (!this.firstContent)
            store.state.planeTabIsModified[this.index] = true;
          else this.firstContent = false;
        }
      });

      // 获取数据
      this.getContent();
    },
    getContent() {
      Request({
        url: "/api/project/mindmap/content",
        method: "post",
        data: {
          projectId: this.$route.params.projectId,
          id: this.id,
        },
      }).then(({ data }) => {
        if (data.code === 0) {
          let defaultData = {
            data: {
              text: "根节点",
            },
            children: [],
          };
          if (data.data == null) {
            this.mindMap.setData(defaultData);
          } else {
            try {
              this.mindMap.setFullData(JSON.parse(data.data));
            } catch (e) {
              this.mindMap.setData(defaultData);
            }
          }
        } else {
          ElMessage.error(data.msg);
        }
      });
    },
    getFirstActiveNode() {
      if (this.activeNodes.length === 0) {
        this.$message.warning("请选择节点");
        return null;
      }
      return this.activeNodes[0];
    },
    setIcon(type, name) {
      let key = type + "_" + name;
      // 检查当前节点是否存在该图标
      let index = this.currentIconList.findIndex((item) => {
        return item === key;
      });
      // 存在则删除icon
      if (index !== -1) {
        this.currentIconList.splice(index, 1);
      } else {
        // 否则判断当前图标是否和要插入的图标是一个组的
        let typeIndex = this.currentIconList.findIndex((item) => {
          return item.split("_")[0] === type;
        });
        // 是一个组的则进行替换
        if (typeIndex !== -1) {
          this.currentIconList.splice(typeIndex, 1, key);
        } else {
          // 否则添加icon
          this.currentIconList.push(key);
        }
      }
      this.activeNodes.forEach((node) => {
        node.setIcon([...this.currentIconList]);
      });
    },
    getLink() {
      let first = this.getFirstActiveNode();
      if (!first) return;
      this.setLinkData = {
        url: first.getData("hyperlink"),
        alt: first.getData("hyperlinkTitle"),
      };
      this.setLinkDialog = true;
    },
    setLink() {
      this.activeNodes.forEach((node) => {
        node.setHyperlink(this.setLinkData.url, this.setLinkData.alt);
      });
      this.setLinkDialog = false;
      this.setLinkData = {};
    },
    formatBrush() {
      let first = this.getFirstActiveNode();
      if (!first) return;
      this.formatBrushStyles = first.effectiveStyles || {};
      // console.log(this.formatBrushStyles);
    },
    getImg() {
      let first = this.getFirstActiveNode();
      if (!first) return;
      this.setImgData = {
        url: first.getData("image"),
        alt: first.getData("imageTitle"),
      };
      this.setImgDialog = true;
    },
    setImg() {
      if (this.setImgIsUpload) {
        ElMessage.warning("图片还未上传成功！请稍后再试。");
        console.log("图片还未上传成功！请稍后再试。");
        return;
      }

      this.activeNodes.forEach((node) => {
        node.setImage({
          url: this.setImgData.url,
          title: this.setImgData.alt,
          width: 100,
          height: 100,
        });
      });
      this.setImgData = {};
      this.setImgDialog = false;
    },
    async uploadImg(options) {
      // console.log(options);
      let file = options.file;
      if (file == null) {
        ElMessage.error("请选择图片");
        return;
      }
      // 图片文件格式验证
      if (file.type.indexOf("image") === -1) {
        ElMessage.error("请上传图片");
        return;
      }
      // 大小 <= 2M
      if (file.size > 2 * 1024 * 1024) {
        ElMessage.error("图片大小不能超过2M");
        return;
      }

      let formdata = new FormData();
      formdata.append("image", file);
      return Request({
        url: "/api/project/doc/upload/image",
        method: "post",
        data: formdata,
        headers: {
          "Content-Type": "multipart/form-data",
        },
      }).then(({ data }) => {
        if (data.code === 0) {
          this.setImgData = {
            url: data.data.url,
            alt: file.name,
          };
          // this.$refs["setImgUploadRef"].clearFiles();
        } else {
          console.log(data);
          ElMessage.error(data.msg);
        }
      });
    },
    handleImgUploadExceed(files) {
      const upload = this.$refs["setImgUploadRef"];
      upload.clearFiles();
      const file = files[0];
      file.uid = genFileId();
      upload.handleStart(file);
    },
    saveMindMap() {
      // console.log("saveMindMap");
      // console.log(this.mindMap.getData(true));
      if (store.state.planeTabIsModified[this.index]) {
        Request({
          url: "/api/project/mindmap/content/save",
          method: "post",
          data: {
            projectId: this.$route.params.projectId,
            id: this.id,
            content: JSON.stringify(this.mindMap.getData(true)),
          },
        }).then(({ data }) => {
          if (data.code === 0) {
            ElMessage.success("保存成功");
            store.state.planeTabIsModified[this.index] = false;
          } else {
            ElMessage.error(data.msg);
          }
        });
      }
    },
  },
  computed: {
    store() {
      return store;
    },
    IconParkList() {
      return {
        Back,
        Next,
        FormatBrush,
        AdjacentItem,
        AddSubset,
        Delete,
        Picture,
        SmilingFace,
        Link,
        EditOne,
        TagOne,
        Save,
        FullScreenOne,
      };
    },
    hasRoot() {
      return (
        this.activeNodes.findIndex((node) => {
          return node.isRoot;
        }) !== -1
      );
    },
    // hasGeneralization() {
    //   return (
    //     this.activeNodes.findIndex((node) => {
    //       return node.isGeneralization;
    //     }) !== -1
    //   );
    // },
    hasActiveNodes() {
      return this.activeNodes.length > 0;
    },
  },
  mounted() {
    this.mindMapEl = document.getElementById("mindMapContainer");
    this.initMindMap();
  },
};
</script>

<template>
  <div id="mindMapContainer"></div>
  <el-card class="mind-map-tool-bar" body-class="mind-map-tool-bar-body">
    <MindMapBarButton
      :active="store.state.planeTabIsModified[index]"
      :icon="IconParkList.Save"
      @click="saveMindMap"
    >
      保存
    </MindMapBarButton>

    <MindMapBarButton
      :active="!isStart"
      :icon="IconParkList.Back"
      @click="mindMap.execCommand('BACK')"
    >
      回退
    </MindMapBarButton>

    <MindMapBarButton
      :active="!isEnd"
      :icon="IconParkList.Next"
      @click="mindMap.execCommand('FORWARD')"
    >
      前进
    </MindMapBarButton>

    <MindMapBarButton :active="hasActiveNodes" @click="formatBrush">
      <template #icon>
        <el-icon>
          <FormatBrush
            :theme="this.formatBrushStyles == null ? 'outline' : 'filled'"
            size="24"
            :fill="
              hasActiveNodes
                ? this.formatBrushStyles == null
                  ? '#000000'
                  : '#E6A23C'
                : '#9b9b9b'
            "
            strokeLinecap="square"
          />
        </el-icon>
      </template>
      格式刷
    </MindMapBarButton>

    <MindMapBarButton
      :active="hasActiveNodes && !hasRoot"
      :icon="IconParkList.AdjacentItem"
      @click="mindMap.execCommand('INSERT_NODE')"
    >
      同级节点
    </MindMapBarButton>

    <MindMapBarButton
      :active="hasActiveNodes"
      :icon="IconParkList.AddSubset"
      @click="mindMap.execCommand('INSERT_CHILD_NODE')"
    >
      子节点
    </MindMapBarButton>

    <MindMapBarButton
      :active="hasActiveNodes && !hasRoot"
      :icon="IconParkList.Delete"
      @click="mindMap.execCommand('REMOVE_NODE')"
    >
      删除节点
    </MindMapBarButton>

    <MindMapBarButton
      :active="hasActiveNodes"
      :icon="IconParkList.Picture"
      @click="getImg"
    >
      图片
    </MindMapBarButton>

    <MindMapBarButton
      :active="hasActiveNodes"
      :icon="IconParkList.SmilingFace"
      @click="iconDrawerVisible = true"
    >
      图标
    </MindMapBarButton>

    <MindMapBarButton
      :active="hasActiveNodes"
      :icon="IconParkList.Link"
      @click="getLink"
    >
      超链接
    </MindMapBarButton>

    <!-- <MindMapBarButton :active="hasActiveNodes" :icon="IconParkList.EditOne">
        备注
      </MindMapBarButton>

      <MindMapBarButton :active="hasActiveNodes" :icon="IconParkList.TagOne">
        标签
      </MindMapBarButton> -->

    <!-- <MindMapBarButton
      :active="true"
      :icon="IconParkList.FullScreenOne"
      @click="() => {}"
      >
      全屏
    </MindMapBarButton> -->
  </el-card>

  <el-drawer
    v-if="mindMapEl"
    v-model="iconDrawerVisible"
    :modal="false"
    :close-on-press-escape="false"
    modal-class="icon-drawer-modal"
    class="icon-drawer"
    size="100%"
    title="节点图标"
  >
    <div v-for="item in nodeIconList" :key="item.type" class="mb-10">
      <el-text>{{ item.name }}</el-text>
      <br />
      <el-icon
        v-for="icon in item.list"
        :key="icon.name"
        size="24"
        class="mb-5 mr-5 mt-5"
      >
        <a v-html="icon.icon" @click="setIcon(item.type, icon.name)"></a>
      </el-icon>
    </div>
  </el-drawer>

  <el-dialog v-model="setLinkDialog" title="超链接" width="550">
    <el-form :model="setLinkData">
      <el-form-item label="链接" :label-width="60">
        <el-input
          v-model="setLinkData.url"
          autocomplete="off"
          placeholder="https://www.xxx.com/"
        />
      </el-form-item>
      <el-form-item label="名称" :label-width="60">
        <el-input
          v-model="setLinkData.alt"
          autocomplete="off"
          placeholder="名称"
        />
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="setLinkDialog = false">取消</el-button>
      <el-button type="primary" @click="setLink"> 确定 </el-button>
    </template>
  </el-dialog>

  <el-dialog v-model="setImgDialog" title="节点图片" width="550">
    <el-radio-group v-model="setImgMode" class="mb-30">
      <el-radio-button value="url">链接添加图片</el-radio-button>
      <el-radio-button value="upload">本地上传图片</el-radio-button>
    </el-radio-group>

    <div class="wp-100" v-show="setImgMode === 'url'">
      <el-form :model="setImgData">
        <el-form-item label="链接" :label-width="60">
          <el-input
            v-model="setImgData.url"
            autocomplete="off"
            placeholder="https://www.xxx.com/img/xxx.jpg"
          />
        </el-form-item>
        <el-form-item label="名称" :label-width="60">
          <el-input
            v-model="setImgData.alt"
            autocomplete="off"
            placeholder="名称"
          />
        </el-form-item>
      </el-form>
    </div>

    <div class="wp-100" v-show="setImgMode === 'upload'">
      <el-upload
        ref="setImgUploadRef"
        class="wp-100"
        drag
        :multiple="false"
        :limit="1"
        :http-request="uploadImg"
        :on-exceed="handleImgUploadExceed"
        :before-upload="
          (f) => {
            setImgIsUpload = true;
            return true;
          }
        "
        :on-success="
          (r, f, l) => {
            setImgIsUpload = false;
          }
        "
      >
        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
        <div class="el-upload__text">将文件拖到此处或<em>点击上传</em></div>
        <template #tip>
          <div class="el-upload__tip">
            仅支持 jpg/png 格式，且大小不超过 2MB
          </div>
        </template>
      </el-upload>
    </div>
    <template #footer>
      <el-button @click="setImgDialog = false">取消</el-button>
      <el-button type="primary" @click="setImg"> 确定 </el-button>
    </template>
  </el-dialog>
</template>

<style scoped>
#mindMapContainer {
  position: relative;
  margin: 0;
  padding: 0;
  width: 100%;
  height: calc(100vh - 160px);
}

#mindMapContainer * {
  padding: 0;
  margin: 0;
}

.mind-map-tool-bar {
  position: absolute;
  margin: 0;
  padding: 0;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  width: auto;
  max-width: 100%;
  height: auto;
  z-index: 999;
}

.mind-map-tool-bar-body {
  padding: 10px 20px;
}

.icon-drawer-modal {
  position: absolute !important;
  width: 30%;
  height: calc(100% - 116px);
  margin-left: auto;
  margin-top: auto;
}

.icon-drawer {
  border-radius: 4px 0 0 0;
}

.icon-drawer a:hover {
  cursor: pointer;
}
</style>